package com.s2.m.btchat;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Hashtable;
import javax.microedition.io.StreamConnection;

/**
 *  
 * @author Samik Saha
 */
public abstract class ChatHandler {

    /**
     * Keep the stream connection reference
     */
    private StreamConnection conn;
    /**
     * The data output stream reference
     */
    private DataOutputStream dos;
    /**
     * The data input stream reference
     */
    private DataInputStream dis;
    /**
     * Friend's profile
     */
    private FriendsProfile friendsProfile = null;
    /**
     * Keep the friend's username
     */
    private String buddyName = "Friend";
    /**
     * Receiver thread reference
     */
    private Thread receiverThread;
    /**
     * The Chat Screen to interact with the user
     */
    private ChatScreen chatScreen = null;

    /**
     * Creates a ChatHandler instance
     * @param conn The StreamConnection object
     */
    public ChatHandler(StreamConnection conn) {
        this.conn = conn;

        try {
            dis = conn.openDataInputStream();
            dos = conn.openDataOutputStream();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    protected void showChatScreen() {
        if (chatScreen == null) {
            chatScreen = new ChatScreen(this);
        }
        chatScreen.showUI();
    }

    /**
     * Starts the message receiver thread
     */
    protected void startMessageReceiver() {
        //create a new MessageReceiver instance
        MessageReceiver mr = new MessageReceiver(this, dis);
        //start Message Receiver in a new Thread
        receiverThread = new Thread(mr, "Message Receiver");
        receiverThread.start();
    }

    /**
     * Sends local user's profile to the remote device
     */
    protected void sendProfile() {
        try {
            //send my profile
            dos.writeUTF(MyProfile.getUsername());
            dos.writeUTF(MyProfile.getFullName());
            dos.writeUTF(MyProfile.getAboutMe());
            dos.writeUTF(MyProfile.getAge());
            dos.writeUTF(MyProfile.getSex());
            dos.writeUTF(MyProfile.getProfession());
            dos.flush();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    /**
     * receives the remote users profile
     */
    protected void receiveFriendsProfile() {
        if (friendsProfile == null) {
            friendsProfile = new FriendsProfile();
        }
        String[] pVal = new String[6];
        try {
            for (int i = 0; i < 6; i++) {
                pVal[i] = dis.readUTF();
            }
            friendsProfile.setProfileValues(pVal);//insert profile values
            if (!(pVal[0].trim().equals(""))) {
                buddyName = pVal[0];//set the buddyname
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    /**
     * Setter method to set the friendsProfie
     * @param profile
     */
    public void setFriendsProfile(FriendsProfile profile) {
        this.friendsProfile = profile;
        if (!(friendsProfile.getUsername().trim().equals(""))) {
            buddyName = friendsProfile.getUsername();//set the buddy name
        }
    }

    /**
     * Getter method to get the friend's profile
     * @return a FriendsProfile object corresponding to the current buddy
     */
    public FriendsProfile getFriendsProfile() {
        return friendsProfile;
    }

    /**
     * Do stuff when the first message received from the remote user
     */
    public abstract void firstMessageReceived();

    /**
     * Appends the message to the conversaion with a label of friends username.
     * The receiverThread calls this methos whenever it receives a message
     * @param msg
     */
    public void MessageReceived(String msg) {
        chatScreen.appendMessage(BTChat.REMOTE_USER, msg);
    }

    /**
     * Called by the receiver thread when it no longer can receive
     */
    public void cannotReceive() {
        if (chatScreen != null && !chatScreen.isTerminated()) {
            chatScreen.disableSending();
            chatScreen.appendMessage(BTChat.SYSTEM, "disconnected");
        } else {
            close();
        }
    }

    /**
     * Sends a string to the remote device
     * @param message
     */
    public void sendMessage(String message) {
        try {
            dos.writeUTF(message);
            dos.flush();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    /**
     * Closes open Streams and Connections
     */
    public void close() {
        if (chatScreen != null) {
            ChatScreen.activeChats.remove(buddyName);
        }
        try {
            dos.close();
            dis.close();
            conn.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    /**
     * Getter method to get friend's username
     * @return Friend's username
     */
    public String getBuddyName() {
        return buddyName;
    }
}
